﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using AutoMapper;
using log4net;
using sharp_net;
using sharp_net.Domain;
using sharp_net.Repositories;
using sharp_net.Specifications;
using zkdao.Domain;
using zkdao.Enum;

namespace zkdao.Application {

    public class UserApplication : BaseApplication, IUserService {

        public UserData GetByID(Guid ID) {
            using (var context = IocLocator.Instance.GetImple<IRepositoryContext>()) {
                var userRepository = context.GetRepository<User>();
                var user = userRepository.GetById(ID);
                if (user == null)
                    return null;
                var userData = Mapper.Map<User, UserData>(user);
                return userData;
            }
        }

        public UserData GetByKey(string userkey) {
            using (var context = IocLocator.Instance.GetImple<IRepositoryContext>()) {
                var userRepository = context.GetRepository<User>();
                var customer = userRepository.Find(Specification<User>.Eval(c => c.Email == userkey));
                if (customer == null)
                    return null;
                var userData = Mapper.Map<User, UserData>(customer);
                return userData;
            }
        }

        public int GetCount(){
            using (var context = IocLocator.Instance.GetImple<IRepositoryContext>()) {
                var userRepository = context.GetRepository<User>();
                var users = userRepository.FindAll();
                return users.Count();
            }
        }

        public IEnumerable<UserData> GetPager(int pageIndex, int pageSize) {
            using (var context = IocLocator.Instance.GetImple<IRepositoryContext>()) {
                var userRepository = context.GetRepository<User>();
                var users = userRepository.FindAll(pageIndex, pageSize);
                if (users == null)
                    return null;
                var userDatas = new List<UserData>();
                foreach (var user in users) {
                    userDatas.Add(Mapper.Map<User, UserData>(user));
                }
                return userDatas;
            }
        }

        public UserData Register(UserData dataObject) {
            if (dataObject == null)
                throw new ArgumentNullException("userDataObject");
            using (var context = IocLocator.Instance.GetImple<IRepositoryContext>()) {
                var userRepository = context.GetRepository<User>();
                if (userRepository.Exists(Specification<User>.Eval(c => c.Email == dataObject.Email)))
                    throw new DomainException("Customer with the Email of '{0}' already exists.", dataObject.Email);
                User user = Mapper.Map<UserData, User>(dataObject);
                user.Register();
                userRepository.Add(user);
                context.Commit();
                return Mapper.Map<User, UserData>(user);
            }
        }

        public bool Approved(string userkey, string approvedID) {
            using (var context = IocLocator.Instance.GetImple<IRepositoryContext>()) {
                var userRepository = context.GetRepository<User>();
                var user = userRepository.Find(Specification<User>.Eval(c => c.Email == userkey));
                if (user == null)
                    return false;
                if (user.ValiApproved(approvedID)) {
                    userRepository.Update(user);
                    return true;
                }
                return false;
            }
        }

        public void RequestApproved(string userkey) {
            using (var context = IocLocator.Instance.GetImple<IRepositoryContext>()) {
                var userRepository = context.GetRepository<User>();
                var user = userRepository.Find(Specification<User>.Eval(c => c.Email == userkey));
                if (user == null)
                    return;
                user.RequestApproved();
                userRepository.Update(user);
            }
        }

        public bool Validate(string userkey, string password) {
            if (string.IsNullOrEmpty(userkey))
                throw new ArgumentNullException("email");
            if (string.IsNullOrEmpty(password))
                throw new ArgumentNullException("password");
            using (var context = IocLocator.Instance.GetImple<IRepositoryContext>()) {
                var userRepository = context.GetRepository<User>();
                return userRepository.Exists(Specification<User>.Eval(c => c.Email == userkey && c.PasswordHash == password));
            }
        }

        public void Update(string userkey, UserData dataObject) {
            if (string.IsNullOrEmpty(userkey))
                throw new ArgumentNullException("email");
            if (dataObject == null)
                throw new ArgumentNullException("dataObject");
            using (var context = IocLocator.Instance.GetImple<IRepositoryContext>()) {
                var userRepository = context.GetRepository<User>();
                var user = userRepository.Get(Specification<User>.Eval(c => c.Email == userkey));
                user.Update(dataObject);
                userRepository.Update(user);
            }
        }
    }
}